#include "buffer.h"

serbuf::serbuf(UINT_16 buf_size):buf_len(buf_size),pInFront(0),pInRear(0),pOutFront(0),pOutRear(0),InOverflow(0)
{
      InBuf=new UCHAR[buf_size];
      OutBuf=new UCHAR[buf_size];
}

serbuf::serbuf():buf_len(BufferSize),pInFront(0),pInRear(0),pOutFront(0),pOutRear(0),InOverflow(0)
{
      InBuf=new UCHAR[BufferSize];
      OutBuf=new UCHAR[BufferSize];
}

serbuf::~serbuf()
{
      delete[] InBuf;
      delete[] OutBuf;
}

COM7_Buf::COM7_Buf(UINT_16 buf_size): serbuf(buf_size)
{
     frameOn=0;
     RcvOk=1;
     frameLen=COM7_Data_Out_Len;
     frameInLen=COM7_Data_In_Len;
     count=0;
     FrameIn=new UCHAR[frameLen*2];
     DataIn=new UCHAR[frameLen];
     FrameOut=new UCHAR[frameLen*2];
     DataOut=new UCHAR[frameLen];
     DataOut[0]=0x7e;
     DataOut[frameLen-1]=0x7e;
     DataOut[1]=0x60;
}

COM7_Buf::COM7_Buf(): serbuf()
{
     frameOn=0;
     RcvOk=1;
     frameLen=COM7_Data_Out_Len;
     frameInLen=COM7_Data_In_Len;
     count=0;
     FrameIn=new UCHAR[frameLen*2];
     DataIn=new UCHAR[frameLen];
     FrameOut=new UCHAR[frameLen*2];
     DataOut=new UCHAR[frameLen];
     DataOut[0]=0x7e;
     DataOut[frameLen-1]=0x7e;
     DataOut[1]=0x60;
}

COM7_Buf::~COM7_Buf()//{serbuf::~serbuf();}
{
     serbuf::~serbuf();
     delete[] FrameIn;
     delete[] DataIn;
     delete[] FrameOut;
     delete[] DataOut;
}

void serbuf::WriteInBuf(UCHAR elem)
{
     InBuf[pInFront++]=elem;
     if(pInFront>=buf_len)
       {
	  pInFront=0;
       }
     if(pInFront==pInRear)
       {
	  InOverflow=1;
       }
}

void serbuf::pt_In_Align(void)
{
//     if(InOverflow&&(pInFront>pInRear))
     if(InOverflow)
       {
	  pInRear=pInFront;
       }
}

void serbuf::WriteOutBuf(UCHAR elem)
{
     OutBuf[pOutFront++]=elem;
     if(pOutFront>=buf_len)
       {
	  pOutFront=0;
       }
     if(pOutFront==pOutRear)
       {
	  OutOverflow=1;
       }
}

void serbuf::pt_Out_Align(void)
{
//     if(OutOverflow&&(pOutFront>pOutRear))
     if(OutOverflow)
       {
	  pOutRear=pOutFront;
       }
}

UINT_16 serbuf::ReadInBuf(UCHAR *out_buf)
{
     UINT_16 bytes=0;

     while(pInRear!=pInFront||InOverflow)
       {
	  if(InOverflow)
	    {
	       InOverflow=0;
	    }
	  out_buf[bytes++]=InBuf[pInRear++];
	  if(pInRear>=buf_len)
	    {
	       pInRear=0;
	    }
       }
     return bytes;
}

UINT_16 serbuf::ReadOutBuf(UCHAR *out_buf)
{
     UINT_16 bytes=0;

     while(pOutRear!=pOutFront||OutOverflow)
       {
	  if(OutOverflow)
	    {
	       OutOverflow=0;
	    }
	  out_buf[bytes++]=OutBuf[pOutRear++];
	  if(pOutRear>=buf_len)
	    {
	       pOutRear=0;
	    }

       }

     return bytes;
}

UINT_16 COM7_Buf::GetFrame(void)
{
     UINT_16 bytes=0;

     while(pInRear!=pInFront||InOverflow)
       {
	  if(InOverflow)
	    {
	       InOverflow=0;
	    }

	  FrameIn[count]=InBuf[pInRear++];

	  if(pInRear>=buf_len)
	    {
	       pInRear=0;
	    }

	  if(!frameOn&&FrameIn[count]==0x7e)
	    {
	       frameOn=1;
	       count++;
	       bytes++;
	    }
	  else if(frameOn)
	    {
	       if(FrameIn[count]==0x7e)
		 {
		    if(count<frameInLen-1)
		      {
			 RcvOk=0;
			 count=0;
			 FrameIn[count++]=0x7e;
			 bytes=1;
		      }
		    else
		      {
			 RcvOk=1;
			 frameOn=0;
			 count++;
			 bytes++;
			 break;
		      }
		 }
	       else
		 {
		    count++;
		    bytes++;
		 }
	    }
	  else
	    {

	    }

       }
     return bytes;
}

UINT_16 COM7_Buf::Decoding(void)
{
     if(!frameOn&&count)
       {
	  for(int i=0,j=0;i<count;i++)
	    {
	       if(FrameIn[i]==0x40)
		 {
		    if(FrameIn[i+1]==0xc0)
		      DataIn[j++]=FrameIn[++i]&0x7f;
		    else if(FrameIn[i+1]==0xfe)
		      DataIn[j++]=FrameIn[++i]&0x7f;
		    else
		      DataIn[j++]=FrameIn[i];
		 }
	       else
		 {
		    DataIn[j++]=FrameIn[i];
		 }
	    }
	  count=0;
	  return j;
       }
     else
	  return 0;
}

UINT_16 COM7_Buf::Encoding(void)
{

     for(int i=0,j=0;i<frameLen;i++)
	    {
	       if(i==0||i==frameLen-1)
		 {
		    FrameOut[j++]=DataOut[i];		//=0x7e
		 }
	       else if(DataOut[i]==0x40||DataOut[i]==0x7e)
		 {
		    FrameOut[j++]=0x40;
		    FrameOut[j++]=DataOut[i]|0x80;
		 }
	       else
		 {
		    FrameOut[j++]=DataOut[i];
		 }
	    }

     return j;

}

UINT_16 COM7_Buf::GetData(UCHAR *in_buf)
{
     UINT_16 bytes=0;

     GetFrame();
     bytes=Decoding();
     for(int i=0;i<bytes;i++)
       {
	  in_buf[i]=DataIn[i];
       }

     return bytes;
}

UINT_16 COM7_Buf::InDataProc(UCHAR *in_buf)
{
     UINT_16 bytes=0;
     UCHAR CheckSum;

     GetFrame();
     bytes=Decoding();

     if(bytes)
	 {
		CheckSum=0;
		for(int i=1;i<frameInLen-2;i++)
		  {
		     CheckSum^=DataIn[i];
		  }
		if(DataIn[frameInLen-2]==CheckSum)
		  {
		     RcvOk=1;			 
		  }
		else
		  {
		     RcvOk=0;		     
		  }
		for(i=0;i<frameInLen;i++)
			{
			in_buf[i]=DataIn[i];
			}
		return i;
       }

     return 0;
}

UINT_16 COM7_Buf::PutFrame(void)
{
     UINT_16  bytes;

     bytes=Encoding();
     for(int i=0;i<bytes;i++)
       {
	  WriteOutBuf(FrameOut[i]);
       }
     pt_Out_Align();

     return 0;
}

UINT_16 COM7_Buf::PutData(UCHAR *out_buf,UINT_16 num)
{
     for(int i=0;i<num;i++)
       {
	  DataOut[i]=out_buf[i];
       }

     return 0;
}

UCHAR COM7_Buf::GetRcvFlag(void)
{
     if(RcvOk)
       {
	  return 0x16;
       }
     else
       {
	  return 0x50;
       }
}
